﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
using System.Collections;
using SAP.Middleware.Connector;
using System.Configuration;

namespace CMD.BAL.SAP
{
    class SvcSAP
    {
        #region properties

        DataTable dtChangeSap;

        public DataTable DtChangeSap
        {
            get { return dtChangeSap; }
            set { dtChangeSap = value; }
        }

        DataTable dtMsgSap;

        public DataTable DtMsgSap
        {
            get { return dtMsgSap; }
            set { dtMsgSap = value; }
        }

        DataTable dtInputSap;

        public DataTable DtInputSap
        {
            get { return dtInputSap; }
            set { dtInputSap = value; }
        }


        IRfcFunction fn;
        RfcRepository repository;
        RfcDestination rfcDest;
        IRfcTable tblInput;        //ZLSMXS010
        IRfcTable tblChange;      //ZLSMXS012
        IRfcTable tblMsg;           //ZLSMXS011
        #endregion

        public SvcSAP()
        {


            RfcConfigParameters param = new RfcConfigParameters();

            //param.Add(RfcConfigParameters.Name, ConfigurationManager.AppSettings["RFCName"].ToString());
            //param.Add(RfcConfigParameters.AppServerHost, ConfigurationManager.AppSettings["RFCServer"].ToString());
            //param.Add(RfcConfigParameters.SystemNumber, ConfigurationManager.AppSettings["RFCSysNumber"].ToString());
            //param.Add(RfcConfigParameters.User, ConfigurationManager.AppSettings["RFCUser"].ToString());
            //param.Add(RfcConfigParameters.Password, ConfigurationManager.AppSettings["RFCPsswd"].ToString());    //"inicio01");
            //param.Add(RfcConfigParameters.Client, ConfigurationManager.AppSettings["RFCClient"].ToString());  // 382
            //param.Add(RfcConfigParameters.Language, ConfigurationManager.AppSettings["RFCLang"].ToString());
            //param.Add(RfcConfigParameters.PoolSize, ConfigurationManager.AppSettings["RFCPoolSize"].ToString());
            //param.Add(RfcConfigParameters.IdleTimeout, ConfigurationManager.AppSettings["RFCIdleTimeOut"].ToString());

            param.Add(RfcConfigParameters.Name, "I_MX_MFBF");
            param.Add(RfcConfigParameters.AppServerHost, "PMICHSAPLCD01.app.pmi"); //"PMICHSAPLA30_LCD_64.app.pmi");
            param.Add(RfcConfigParameters.SystemNumber, "64");
            param.Add(RfcConfigParameters.User, "I_MX_MFBF");
            param.Add(RfcConfigParameters.Password, "inicio01");    //"inicio01");
            param.Add(RfcConfigParameters.Client, "382");  // 382
            param.Add(RfcConfigParameters.Language, "ES");
            param.Add(RfcConfigParameters.PoolSize, "10");
            param.Add(RfcConfigParameters.IdleTimeout, "1000");

            try
            {
                //session.Connect();
                this.rfcDest = RfcDestinationManager.GetDestination(param);
                this.repository = this.rfcDest.Repository;
                this.fn = this.repository.CreateFunction("ZLMXS_CUSTOMER");  // ZLMXS_CUSTOMER  Z_LARM_POST_BACKFLUSH_MFBF
                
                this.fn.Invoke(rfcDest);


                //tablas que devuelve la fn de SAP
                this.tblInput = fn.GetTable("T_INPUT");        //ZLSMXS010
                this.tblChange = fn.GetTable("T_CHANGE");      //ZLSMXS012
                this.tblMsg = fn.GetTable("T_OUTPUT");         //ZLSMXS011 

            }
            catch (Exception ex)
            {
                throw ex;
            }


        }

        /// <summary>
        /// Pasa datos en estructura de INPUT. Útil en ALTA y CONSULTA
        /// </summary>
        /// <param name="dictInput">Diccionario con estructura INPUT</param>
        public void InputSAP(Dictionary<string, string> dictInput)
        {
            DataToInputTable(dictInput);


        }////// 

        public void ChangeSAP(Dictionary<string, string> dictChange)
        {
            try
            {
                RfcStructureMetadata metadata = repository.GetStructureMetadata("ZLSMXS012");
                IRfcStructure str = metadata.CreateStructure();

                //paso de valores a la estructura de SAP
                foreach (var item in dictChange)
                {
                    str.SetValue(item.Key, item.Value);
                }

                //actualización de tabla de cambio
                tblChange.Append(str);

                //envío de datos a SAP
                fn.Invoke(rfcDest);

                //------------------------ lectura de resultados de SAP 
                ReadDataFromSAP();
            }
            catch (Exception ex)
            {

                throw ex;
            }


        }///////////

        /// <summary>
        /// Le pasa un Dicionario con la estructura de la tabla de ALTA (INPUT) a la función de SAP. Puede usarse en Altas y en Consultas
        /// </summary>
        /// <param name="dictInput">Diccionario con la estructura de Entrada</param>
        private void DataToInputTable(Dictionary<string, string> dictInput)
        {
            try
            {
                RfcStructureMetadata metadata = repository.GetStructureMetadata("ZLSMXS010");
                IRfcStructure str = metadata.CreateStructure();

                //paso de valores a la estructura de SAP
                foreach (var item in dictInput)
                {
                    str.SetValue(item.Key, item.Value);
                }

                //actualización de la tabla de entrada
                this.tblInput.Append(str);

                //envío de datos a SAP
                this.fn.Invoke(rfcDest);

                //------------------------ lectura de resultados de SAP 
                ReadDataFromSAP();
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }


        private void ReadDataFromSAP()
        {
            this.dtChangeSap = new DataTable();
            this.dtMsgSap = new DataTable();
            this.dtInputSap = new DataTable();

            #region CHANGES ---------------

            for (int liElement = 0; liElement < tblChange.ElementCount; liElement++)
            {
                RfcElementMetadata element = tblChange.GetElementMetadata(liElement);
                this.dtChangeSap.Columns.Add(element.Name);
            }

            //metadata
            foreach (IRfcStructure row in tblChange)
            {
                DataRow sapdr = this.dtChangeSap.NewRow();
                for (int liElement = 0; liElement < tblChange.ElementCount; liElement++)
                {
                    RfcElementMetadata element = tblChange.GetElementMetadata(liElement);
                    sapdr[element.Name] = row.GetString(element.Name);
                }
                this.dtChangeSap.Rows.Add(sapdr);
            }

            #endregion -------------------------

            #region MESSAGES --------------

            for (int liElement = 0; liElement < tblMsg.ElementCount; liElement++)
            {
                RfcElementMetadata element = tblMsg.GetElementMetadata(liElement);
                this.dtMsgSap.Columns.Add(element.Name);
            }

            foreach (IRfcStructure row in tblMsg)
            {
                DataRow sapdr = this.dtMsgSap.NewRow();
                for (int liElement = 0; liElement < tblMsg.ElementCount; liElement++)
                {
                    RfcElementMetadata element = tblMsg.GetElementMetadata(liElement);
                    sapdr[element.Name] = row.GetString(element.Name);
                }
                this.dtMsgSap.Rows.Add(sapdr);
            }

            #endregion ---------------------

            #region INPUT -------------

            for (int liElement = 0; liElement < tblInput.ElementCount; liElement++)
            {
                RfcElementMetadata element = tblInput.GetElementMetadata(liElement);
                this.dtInputSap.Columns.Add(element.Name);
            }

            foreach (IRfcStructure row in tblInput)
            {
                DataRow sapdr = this.dtInputSap.NewRow();
                for (int liElement = 0; liElement < tblInput.ElementCount; liElement++)
                {
                    RfcElementMetadata element = tblInput.GetElementMetadata(liElement);
                    sapdr[element.Name] = row.GetString(element.Name);
                }
                this.dtInputSap.Rows.Add(sapdr);
            }

            #endregion ------------------
        }

    }// end class
}
